//
//      CGE - CRAb Graphics Engine
// 
//      Copyright (C) 2003-2009 by CRAb-UFC
//
//		This file is part of the "CRAb Graphics Engine"
//		See the copyright notice in cge.h for conditions of distribution and use.
//

#ifndef CGE_DATAGRAMSOCKET_CLASS_H__
#define CGE_DATAGRAMSOCKET_CLASS_H__

#include "cgeDatagramPacket.h"

namespace basterd
{
	namespace net
	{
		/** @brief Encapsulates a Datagram Socket, i.e., a socket oriented to UDP (User Datagram Protocol).
		 *
		 *  @remarks
		 *      This class represents a socket for sending and receiving datagram packets.
		 *      UDP is a connectionless protocol, so each time you send a packet you must specify the
		 * destination address. Hence, this enables to use just one UDP socket to send packets to any 
		 * number of different IP addresses, since there is no one computer at the other end of your UDP
		 * socket that you are connected to.
		 *		Similarly, packets may arrive from any number of different computers. Each time you receive
		 * a packet, it gives you the IP address and port of the sender, so you know where the packet came
		 * from. Conclusion: you can implement a game server by using a single UDP socket.
		 *
		 */
		class DatagramSocket
		{
		public:

			/**
			 * Construtor. Builds an UDP socket and binds it to a given port.
			 *
			 * @param port Port to bound this datagram socket to.
			 * @param nonBlocking Tells whether this socket is non-blocking. Useful for real-time servers,
			 *                    like those for First Person Shooters or Action games. This flag is set to true,
			 *                    by default.
			 */
			DatagramSocket(unsigned short port, bool nonBlocking=true);

			/**
			 * Construtor. Builds an UDP socket and binds it to a given host/port.
			 *
			 * @param host        Human-readable IP address of this host.
			 * @param port        Port to bound this datagram socket to.
			 * @param nonBlocking Tells whether this socket is non-blocking. Useful for real-time servers,
			 *                    like those for First Person Shooters or Action games. This flag is set to true,
			 *                    by default.  
			 */
			DatagramSocket(const String& host, unsigned short port, bool nonBlocking=true);
			
			/**
			 * Destructor
			 */
			virtual ~DatagramSocket(void);

			/**
			 * @param nonBlocking Tells whether this socket I/O operations will be blocking or not.
			 *                    Set to true by default. 
			 */
			bool setNonBlocking(bool nonBlocking=true);
			
			/**
			 * Checks whether this socket is open, i.e., the socket exists and it is bound to the port. 
			 */
			bool isOpen(void) const;
			
			/**
			 *  @brief Receives a packet of data from a remote peer.
			 *
			 *  @remarks
			 *		Packets in the queue larger than your receive buffer will be silently discarded. So 
			 * if you have a 256 byte buffer to receive packets, and somebody sends you a 300 byte packet,
			 * that 300 byte packet will be simply dropped. You will not receive just the first 256 bytes
			 * of the 300 byte packet.
			 *		Since you are writing your own network protocol, this is no problem at all in practice,
			 * just make sure your receive buffer is big enough to receive the largest packet your protocol.
			 * could possibly send.
			 *
			 *      TODO: talk about partial sends!
			 */
			int receive(DatagramPacket& pack);

			/**
			 * @brief Sends a packet of data to a remote peer.
			 *
			 * @return An integer flag telling about the success of this operation. Return values
			 *		   are coded as follows:
			 *			- result < 0 indicates that no data was received at all. When using a non-blocking socket,
			 *			  this means that there is no data available in the buffer;
			 *			- result = 0 indicates that no data was received at all;
			 *			- result > 0 indicates the size of the packet that was sucessfully received;
			 *
			 */
			int    send( const DatagramPacket& pack);
			
			/**
			 * Closes this socket.
			 */
			void close(void);
			
			/**
			 * Access the port to which this socket is bound.
			 */
			unsigned short getPort(void) const;

			/**
			 * 	Access the destination address assigned to this socket
			 */
			const String& getHostAddress(void) const;
			
			/**
			 * Gets the internal socket id used by this datagram socket.
			 */
			__socket getSocketId(void) const { return socketId; }
			
			/**
			 * Gets the internal low-level socket address used by this datagram socket.
			 */
			const sockaddr_in& getSocketAddress() const { return address; }
			
	    private:

       	    /**
			 * Copy-constructor: not allowed
			 */
			DatagramSocket( const DatagramSocket& );
			
			/**
			 * Assignment operator: not allowed
			 */
			DatagramSocket& operator = ( const DatagramSocket& );
			
			/**
			 * Internal low-level socket address used in the low-level implementation.
			 */
			sockaddr_in address;
			
			/**
			 * Internal socket id used on low-level implementation.
			 */
			__socket socketId;
	        
			/**
			 * Address to which this socket is bound to.
			 */
	        String hostAddress;
	        
			/**
			 * Port to which this socket is bound to, thus allowing this receiving data from this port.
			 */
	        unsigned short port;
	    
			/**
			 * Internal method. Creates an UPD socket;
			 */
	        bool create(void);
	        
			/**
			 * Internal method. Binds this socket to a given port.
			 */
	        bool bind(unsigned short port);
	        
			/**
			 * Internal method. Binds this socket to a given host/port.
			 */
	        bool bind(const String& host, unsigned short port);
	        
		}; // end of the DatagramSocket class
		
		/// For ease of coding, defines an DatagramSocket type
		typedef DatagramSocket UdpSocket;
	}
}



#endif // CGE_SERVER_CLASS_H__
